package com.cutler.kelv.wordduel;

import javax.persistence.Id;
import javax.persistence.Transient;

import org.json.JSONException;
import org.json.JSONObject;

import com.googlecode.objectify.Key;
import com.googlecode.objectify.Objectify;
import com.googlecode.objectify.annotation.Entity;
import com.googlecode.objectify.annotation.Indexed;


@Entity
public class Game {

	public @Id Long id;
	
	public @Indexed String playerIds;
	
	public boolean active;
	
	public @Indexed String p1Email;
	public @Indexed String p2Email;
	
	public Key<UserInfo> p1Key;
	public Key<UserInfo> p2Key;

	public @Transient UserInfo p1Info;
	public @Transient UserInfo p2Info;
	
	public String p1Word;
	public String p2Word;
	
	public String p1Alphabet;
	public String p2Alphabet;
	
	public String[] p1Guesses;
	public String[] p2Guesses;
	
	public Game() {}
	
	public Game(UserInfo player1, UserInfo player2, String playerIds) {
		active = true;
		p1Info = player1;
		p2Info = player2;
		p1Email = player1.email;
		p2Email = player2.email;
		p1Alphabet = "abcdefghijklmnopqrstuvwxyz";
		p2Alphabet = "abcdefghijklmnopqrstuvwxyz";
		this.playerIds = playerIds;
		p1Key = new Key<UserInfo>(UserInfo.class, player1.email);
		p2Key = new Key<UserInfo>(UserInfo.class, player2.email);
	}
	
	public void load(Objectify ofy) {
		p1Info = ofy.get(p1Key);
		p2Info = ofy.get(p2Key);
	}
	
	@Override
	public String toString() {
		return toJSON().toString();
	}
	
	public JSONObject toJSON() {
		JSONObject jObject = new JSONObject();
		try {
			jObject.put("Id", id);
			
			if (p1Info != null) {
				jObject.put("Player1", p1Info.toJSON());
			}
			if (p2Info != null) {
				jObject.put("Player2", p2Info.toJSON());
			}
			
			jObject.put("P1Word", p1Word);
			jObject.put("P2Word", p2Word);
			jObject.put("P1Guesses", p1Guesses);
			jObject.put("P1GuessCounts", getP1GuessCounts());
			jObject.put("P2Guesses", p2Guesses);
			jObject.put("P2GuessCounts", getP2GuessCounts());
			jObject.put("P1Alphabet", p1Alphabet);
			jObject.put("P2Alphabet", p2Alphabet);
			jObject.put("Active", active);
			if (getWinner() != null)
				jObject.put("Winner", getWinner());
			jObject.put("p1CanGuess", (p2Word != null && p1Guesses == null) || (p2Word != null && p2Guesses != null && p1Guesses.length <= p2Guesses.length));
			jObject.put("p2CanGuess", (p1Word != null && p2Guesses == null) || (p1Word != null && p1Guesses != null && p2Guesses.length <= p1Guesses.length));
		} catch (JSONException e) {}
		return jObject; 
	}
	
	public static int getGuessCount(String word, String guess) {
		int count = 0;
		boolean[] used = new boolean[4];
		for (int i=0; i<4; i++) {
			inner: for (int j=0; j<4; j++) {
				if (!used[j] && guess.charAt(i) == word.charAt(j)) {
					used[j] = true;
					count++;
					break inner;
				}
			}
		}
		return count;
	}
	
	private int[] getP1GuessCounts() {
		if (p1Guesses == null) {
			return null;
		}
		int[] counts = new int[p1Guesses.length];
		
		for (int g=0; g<p1Guesses.length; g++) {
			counts[g] = Game.getGuessCount(p2Word, p1Guesses[g]); 
		}
		return counts;
	}
	
	private int[] getP2GuessCounts() {
		if (p2Guesses == null) {
			return null;
		}
		int[] counts = new int[p2Guesses.length];
		
		for (int g=0; g<p2Guesses.length; g++) {
			counts[g] = Game.getGuessCount(p1Word, p2Guesses[g]); 
		}
		return counts;
	}
	
	public String getWinner() {
		if (p2Guesses == null || p1Guesses == null) 
			return null;
		if (p2Guesses.length != p1Guesses.length) 
			return null;
		if (p2Guesses[p2Guesses.length-1].equals(p1Word))
			if (p1Guesses[p1Guesses.length-1].equals(p2Word)) 
				return "tie";
			else
				return "p2";
		else
			if (p1Guesses[p1Guesses.length-1].equals(p2Word)) 
				return "p1";
			else
				return null;
	}
}
